/**
 * A FriendFeed Entry
 * Use this class to publish information on FriendFeed
 * 
 * @author	Lucas Araujo <araujo.lucas [at] gmail.com> - http://FriendFeed.com/LucasAraujo
 */
package friendfeed.api.data  
{
	import flash.net.URLVariables;
	import flash.utils.ByteArray;
	
	import friendfeed.api.data.Profile;
	
	/**
	 * 
	 */
	public class Entry
	{
		// id - Read-only
		protected var _id:String;
		
		// Title
		public var title:String;
		
		// Link
		public var link:String;
		
		// published
		protected var _published:Date;
		
		// updated
		protected var _updated:Date;
		
		// hidden - if true, this entry should be hidden based on the user's preferences
		protected var _hidden:Boolean;
		
		// anonymous - if true, user will be present but should not be shown 
		protected var _anonymous:Boolean;
		
		// user
		protected var _user:Object;
		
		// service
		protected var _service:Object;
		
		// comments
		protected var _comments:Array;
		
		// likes
		protected var _likes:Array;
		
		// media
		protected var _media:Array;
		
		// via
		protected var _via:Object;
		
		// Room
		protected var _room:*;
		
		// geo - Read-only
		protected var _geo:Object;
		
		// Real-time:
		protected var _is_new:Boolean;
		
		
		// For share only:
		
		// Comment
		public var comment:String;
		
		// Images - Multipart/form-data or url, and link
		protected var images:Array;
		
		// Audios - url and title
		protected var audios:Array;
		
		/**
		 * 
		 */
		public function Entry():void
		{
			this.images = [];
			this.audios = [];
		}
		
		/**
		 * 
		 * @param	obj
		 * @param	link
		 * @param	comment
		 * @return	Entry or null
		 */
		public static function factory(obj:*, link:String=null, comment:String=null, room:String=null):Entry
		{
			var entry:Entry;
			
			// Just a simple message
			if (obj is String)
			{
				entry = new Entry();
				entry.title = (obj as String);
				entry.link = link;
				entry.comment = comment;
				entry.room = room;
			}
			// It's a entry
			else if (obj is Entry)
			{
				entry = (obj as Entry);
			}
			// From a JSON object
			else if (obj is Object)
			{
				entry = Entry.newFromJSON(obj);
			}
			return entry;
		}
		
		/**
		 * 
		 * @param	obj
		 * @return
		 */
		public static function newFromJSON(obj:Object):Entry
		{
			var i:uint;
			var length:uint;
			var entry:Entry = new Entry();

			entry._id = obj.id;
			entry.title = obj.title;
			entry._published = Entry.getDate(obj.published);			
			entry._updated = Entry.getDate(obj.updated);
			entry._hidden = obj.hidden;
			entry._anonymous = obj.anonymous;
			entry._user = friendfeed.api.data.Profile.newFromJSON(obj.user);
			entry._service = obj.service;
			if (obj.comments)
			{
				entry._comments = obj.comments;
				length = obj.comments.length
				for (i = 0; i < length; i++)
				{
					entry._comments[i].date = Entry.getDate(obj.comments[i].date);
					entry._comments[i].user = friendfeed.api.data.Profile.newFromJSON(entry._comments[i].user);
				}
			}
			if (obj.likes)
			{
				entry._likes = obj.likes;
				length = obj.likes.length
				for (i = 0; i < length; i++)
				{
					entry._likes[i].date = Entry.getDate(obj.likes[i].date);
					entry._likes[i].user = friendfeed.api.data.Profile.newFromJSON(entry._likes[i].user);
				}
			}
			entry._media = obj.media;
			entry._via = obj.via;
			entry._room = obj.room;
			entry._geo = obj.geo;
			if (obj.is_new)
				entry._is_new = obj.is_new;
			return entry;			
		}
		
		/**
		 * 
		 * @param	rfc3339date
		 * @return
		 */
		public static function getDate(rfc3339date:String):Date
		{
			// Sample: 2009-02-06T16:37:29Z			
			// result: 02/06/2009 16:37:29
			var dateString:String =	rfc3339date.substr(5, 2) + "/" + 
									rfc3339date.substr(8, 2) + "/" +
									rfc3339date.substr(0, 4);
			var timeString:String = rfc3339date.substr(11, 8);
			return (new Date(dateString+" "+timeString));
		}
		
		/**
		 * 
		 * @param	image
		 * @param	link
		 * @return
		 */
		public function addImage(image:*, link:String=null):uint
		{
			var imgObj:Object = new Object();
			// image is a url
			if (image is String)
			{
				imgObj.url = image;
			}
			// image is a binary file
			else if (image is ByteArray)
			{
			}
			// invalid type
			else
				throw new Error("Invalid image type.");
			imgObj.link = link;
			return this.images.push(imgObj);
		}
		
		/**
		 * 
		 * @param	index
		 * @return
		 */
		public function getImage(index:uint):Object
		{
			return this.images[index];
		}
		
		/**
		 * 
		 * @return
		 */
		public function getImages():Array
		{
			return this.images;
		}
		
		/**
		 * 
		 * @param	index
		 */
		public function removeImage(index:uint):void
		{
			this.images.splice(index, 1);
		}
		
		/**
		 * 
		 * @param	url
		 * @param	title
		 * @return
		 */
		public function addAudio(url:*, title:String=null):uint
		{
			var audioObj:Object = new Object();
			audioObj.url = url;
			audioObj.title = title;
			return this.audios.push(audioObj);
		}
		
		/**
		 * 
		 * @param	index
		 * @return
		 */
		public function getAudio(index:uint):Object
		{
			return this.audios[index];
		}
		
		/**
		 * 
		 * @return
		 */
		public function getAudios():Array
		{
			return this.audios;
		}
		
		/**
		 * 
		 * @param	index
		 */
		public function removeAudio(index:uint):void
		{
			this.audios.splice(index, 1);
		}
		
		/**
		 * 
		 * @return
		 */
		public function toURLVariables():URLVariables
		{
			var variables:URLVariables;
			variables.title = this.title;
			if (this.link)
				variables.link = this.link;
			if (this.comment)
				variables.comment = this.comment;
			if (this.room)
				variables.room = (this.room as String);
				
			// Post images
			var imageCount:uint = 0;
			var fileCount:uint = 0;
			var imagesLength:uint = this.images.length;
			for (var i:uint = 0; i < imagesLength; i++)
			{
				var imgObj:Object = this.images[i];
				if (imgObj.url)
				{
					var imgName:String = "image" + (imageCount++);
					variables[imgName + "_url"] = imgObj.url
					if (imgObj.link)
						variables[imgName + "_link"] = imgObj.link;
				}
				// Not supported for now
				else if (imgObj.file)
				{
				}
			}
			
			// Post Audio
			var audiosLength:uint = this.audios.length;
			for (var j:uint = 0; j < audiosLength; j++)
			{
				var audioObj:Object = this.audios[i];
				var audioName:String = "audio" + j;
				variables[audioName + "_url"] = audioObj.url;
				if (audioObj.title)
					variables[audioName + "_title"] = audioObj.title;
			}
			
			return variables;
		}
		
		/**
		 * toString
		 * 
		 * @return
		 */
		public function toString():String
		{
			return "(Entry id: "+ this.id +")";
		}
		
		// Setters and getters
		
		public function get id():String { return this._id; }
		public function get published():Date { return this._published; }
		public function get updated():Date { return this._updated; }
		public function get hidden():Boolean { return this._hidden; }
		public function get anonymous():Boolean { return this._anonymous; }
		public function get user():Object { return this._user; }
		public function get service():Object { return this._service; }
		public function get comments():Array { return this._comments; }
		public function get likes():Array { return this._likes; }	
		public function get media():Array { return this._media; }	
		public function get via():Object { return this._via; }
		
		public function get room():* { return this._room; }
		public function set room(value:*):void
		{
			if (value is String)
				this._room = value;
			else
				throw new Error("Invalid type. Only String is acceptable.");
		}
		
		public function get geo():Object { return this._geo; }
		public function get is_new():Object { return this._is_new; }
	}
}